package top.riske.gen3d.common.utils;

import cn.hutool.jwt.JWT;
import top.riske.gen3d.common.DTO.JwtDto;
import top.riske.gen3d.enums.RoleEnum;
import top.riske.gen3d.common.exception.AuthorizationExpiredException;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * created by vital on 2025/3/1 下午3:21
 */
public class JWTUtils {

    /**
     * JWT 密钥
     */
    private static final String JWT_SECRET_KEY = "84ef287058a44f8a982b9be69057cc35";

    /**
     * JWT 密钥的字节数组
     */
    private static final byte[] JWT_SECRET_KEY_BYTES = JWT_SECRET_KEY.getBytes();

    /**
     * JWT 过期时间，单位秒
     */
    private static final long JWT_EXPIRE_TIME = 60 * 60 * 24 * 7;

    /**
     * 为用户创建 JWT
     */
    public static String createJWTForUser(Long uid){
        return createToken(uid, RoleEnum.USER);
    }

    /**
     * 为管理员创建 JWT
     */
    public static String createJWTForAdmin(Long uid){
        return createToken(uid, RoleEnum.ADMIN);
    }

    public static void main(String[] args) {
        System.out.println(createToken(1L, RoleEnum.USER));
    }

    /**
     * 创建 JWT
     * @param uid 用户id
     * @param role 角色
     * @return jwt
     */
    public static String createToken(Long uid, RoleEnum role) {
        return JWT.create()
                // 设置用户 ID
                .setPayload("uid", uid)
                // 设置角色
                .setPayload("role", role.getCode())
                // 设置过期时间
                .setExpiresAt(Date.from(LocalDateTime.now().plusSeconds(JWT_EXPIRE_TIME).atZone(ZoneId.systemDefault()).toInstant()))
                .setKey(JWT_SECRET_KEY_BYTES)
                .sign();
    }

    /**
     * 解析 JWT
     */
    public static JwtDto parseJwt(String token) throws AuthorizationExpiredException {
        JWT jwt = JWT.of(token);
        // 解析uid
        Long uid = Long.parseLong(jwt.getPayload("uid").toString());
        // 解析权限
        RoleEnum role = RoleEnum.getRoleEnumByCode(Integer.parseInt(jwt.getPayload("role").toString()));
        // 解析过期时间戳
        Long date = Long.valueOf(jwt.getPayload("exp").toString());
        // 将时间戳转换为时间，将时间戳转换为毫秒，设置系统默认时区
        LocalDateTime expiresAt = LocalDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneId.systemDefault());
        JwtDto jwtDto = new JwtDto(token, uid, role, expiresAt);
        // 判断是否过期
        if(jwtDto.getExpired()){
            throw new AuthorizationExpiredException("token已过期", jwtDto);
        }
        return jwtDto;
    }

}
